temp = Dir.pwd
Dir.chdir(File.dirname(__FILE__))
require 'librbof'
Dir.chdir(temp)

module OF
  def self.private_module_function(name, &block)
    define_method(name, &block)
    module_function(name)
    private_class_method(name)
  end
  private_class_method :private_module_function
  
  def self.wrap_module_function(name, &block)
    orig = "__#{name.to_s}__".to_sym
    alias_method(orig, name)
    module_function(orig)
    private_class_method(orig)
    orig_method = method(orig)
    define_method(name) do |*args|
      block.call(orig_method, args)
    end
    module_function(name)
  end
  private_class_method :wrap_module_function
  
  private_module_function :start_sound_thr do
    @sound_thr = Thread.new do
      loop do
        soundInputStream(&@received)
        soundOutputStream(&@requested)
        soundTickStream
      end
    end
  end
  
  private_module_function :stop_sound_thr do
    @sound_thr.kill if @sound_thr
    @sound_thr = nil
  end
  
  private_module_function :check_initialized do
    unless @initialized
      raise UninitializedError, "the stream is not opened"
    end
  end
  
  wrap_module_function :soundStreamSetup do |orig, args|
    orig.call(*args)
      
    app = args[2]
    @received = app.method(:audioReceived)
    @requested = app.method(:audioRequested)
    
    start_sound_thr
    @initialized = true
  end
  
  wrap_module_function :soundStreamStart do |orig, args|
    check_initialized
    orig.call
    start_sound_thr
  end
  
  wrap_module_function :soundStreamStop do |orig, args|
    check_initialized
    stop_sound_thr
    orig.call
  end
  
  wrap_module_function :soundStreamClose do |orig, args|
    check_initialized
    stop_sound_thr
    orig.call
    @initialized = false
  end
end